/*
    DIMVisual-KAAPI, the DIMVisual bundle for KAAPI trace files
    Copyright (c) 2008 Lucas Mello Schnorr <schnorr@gmail.com>

    This file is part of DIMVisual-KAAPI.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "KAAPIParser.h"

@implementation KAAPIParser (Kernel)
- (GEvent *) coreThreadRun: (Util::RecordReader::const_iterator) r
{
	GEvent *ev = [[GEvent alloc] init];
	GName *name = [[GName alloc] init];
	GFields *fields = [[GFields alloc] init];
	[name setName: @"EVT_CORE_THREAD_RUN"];
	[ev setName: name];
	[name release];
	[ev setFields: fields];
	[fields release];
	[ev autorelease];
	return ev;
}

- (GEvent *) coreThreadCompute: (Util::RecordReader::const_iterator) r
{
	GEvent *ev = [[GEvent alloc] init];
	GName *name = [[GName alloc] init];
	GFields *fields = [[GFields alloc] init];
	[name setName: @"EVT_CORE_THREAD_COMPUTE"];
	[ev setName: name];
	[name release];
	[ev setFields: fields];
	[fields release];
	[ev autorelease];
	return ev;
}

- (GEvent *) coreThreadSuspend: (Util::RecordReader::const_iterator) r
{
	GEvent *ev = [[GEvent alloc] init];
	GName *name = [[GName alloc] init];
	GFields *fields = [[GFields alloc] init];
	[name setName: @"EVT_CORE_THREAD_SUSPEND"];
	[ev setName: name];
	[name release];
	[ev setFields: fields];
	[fields release];
	[ev autorelease];
	return ev;
}

- (GEvent *) coreThreadWakeup: (Util::RecordReader::const_iterator) r
{
	GEvent *ev = [[GEvent alloc] init];
	GName *name = [[GName alloc] init];
	GFields *fields = [[GFields alloc] init];
	[name setName: @"EVT_CORE_THREAD_WAKEUP"];
	[ev setName: name];
	[name release];
	[ev setFields: fields];
	[fields release];
	[ev autorelease];
	return ev;
}

- (GEvent *) coreThreadSteal: (Util::RecordReader::const_iterator) r
{
	GEvent *ev = [[GEvent alloc] init];
	GName *name = [[GName alloc] init];
	GFields *fields = [[GFields alloc] init];
	[name setName: @"EVT_CORE_THREAD_STEAL"];
	[ev setName: name];
	[name release];
	[ev setFields: fields];
	[fields release];
	[ev autorelease];
	return ev;
}

- (GEvent *) coreThreadTerm: (Util::RecordReader::const_iterator) r
{
	GEvent *ev = [[GEvent alloc] init];
	GName *name = [[GName alloc] init];
	GFields *fields = [[GFields alloc] init];
	[name setName: @"EVT_CORE_THREAD_TERM"];
	[ev setName: name];
	[name release];
	[ev setFields: fields];
	[fields release];
	[ev autorelease];
	return ev;
}

- (GEvent *) coreThreadSched: (Util::RecordReader::const_iterator) r
{
	GEvent *ev = [[GEvent alloc] init];
	GName *name = [[GName alloc] init];
	GFields *fields = [[GFields alloc] init];
	[name setName: @"EVT_CORE_THREAD_SCHED"];
	[ev setName: name];
	[name release];
	[ev setFields: fields];
	[fields release];
	[ev autorelease];
	return ev;
}

- (GEvent *) coreThreadSignalWakeup: (Util::RecordReader::const_iterator) r
{
	GEvent *ev = [[GEvent alloc] init];
	GName *name = [[GName alloc] init];
	GFields *fields = [[GFields alloc] init];
	[name setName: @"EVT_CORE_THREAD_SIGNALWAKEUP"];
	[ev setName: name];
	[name release];
	[ev setFields: fields];
	[fields release];
	[ev autorelease];
	return ev;
}

- (GEvent *) coreThreadLsteal: (Util::RecordReader::const_iterator) r
{
	GEvent *ev = [[GEvent alloc] init];
	GName *name = [[GName alloc] init];
	GFields *fields = [[GFields alloc] init];
	[name setName: @"EVT_CORE_THREAD_LSTEAL"];
	[ev setName: name];
	[name release];
	[ev setFields: fields];
	[fields release];
	[ev autorelease];
	return ev;
}

- (GEvent *) coreThreadRetLsteal: (Util::RecordReader::const_iterator) r
{
	GEvent *ev = [[GEvent alloc] init];
	GName *name = [[GName alloc] init];
	GFields *fields = [[GFields alloc] init];
	[name setName: @"EVT_CORE_THREAD_RETLSTEAL"];
	[ev setName: name];
	[name release];
	[ev setFields: fields];
	[fields release];
	[ev autorelease];
	return ev;
}

- (GEvent *) coreThreadRsteal: (Util::RecordReader::const_iterator) r
{
	GEvent *ev = [[GEvent alloc] init];
	GName *name = [[GName alloc] init];
	[name setName: @"EVT_CORE_THREAD_RSTEAL"];
	[ev setName: name];
	[name release];

	GFields *fields = [[GFields alloc] init];
	GIdentifier *ide = [[GIdentifier alloc] init];
	[ide addValue: @"gidvictim"];
	uint64_t gid;
	gid = (uint64_t)*(uint64_t *)r->structure->get_field_data
 			("gidvictim",r->buffer);
	[fields setFieldWithKey: ide 
		withValue: [NSString stringWithFormat: @"%lu", gid]];
	[ev setFields: fields];
	[ide release];
	[fields release];

	[ev autorelease];
	return ev;
}

- (GEvent *) coreThreadRetRsteal: (Util::RecordReader::const_iterator) r
{
	GEvent *ev = [[GEvent alloc] init];
	GName *name = [[GName alloc] init];
	[name setName: @"EVT_CORE_THREAD_RETRSTEAL"];
	[ev setName: name];
	[name release];

	GFields *fields = [[GFields alloc] init];
	GIdentifier *gidide = [[GIdentifier alloc] init];
	GIdentifier *retvalide = [[GIdentifier alloc] init];
	[gidide addValue: @"gidvictim"];
	[retvalide addValue: @"retval"];
	uint64_t gid;
	uint16_t retval;
	gid = (uint64_t)*(uint64_t *)r->structure->get_field_data 
						("gidvictim",r->buffer);
	retval = (uint16_t)*(uint16_t *)r->structure->get_field_data
						("retval",r->buffer);
	[fields setFieldWithKey: gidide 
		withValue: [NSString stringWithFormat: @"%lu", gid]];
	[fields setFieldWithKey: retvalide
		withValue: [NSString stringWithFormat: @"%d", 
				(unsigned int)retval]];
	[ev setFields: fields];
	[gidide release];
	[retvalide release];
	[fields release];

	[ev autorelease];
	return ev;
}

- (GEvent *) parseKAAPIKernelLevel: (Util::RecordReader::const_iterator) r
	withIdentifier: (GIdentifier *) identifier
	withTimestamp: (GTimestamp *) timestamp
{
	int event;
	event = (int)*(char *)r->structure->get_field_data("_event",r->buffer);

	GEvent *ev = nil;
	switch (event){
		case Event::CORE_THREAD_RUN:
			ev = [self coreThreadRun: r];
			break;
		case Event::CORE_THREAD_COMPUTE:
			ev = [self coreThreadCompute: r];
			break;
		case Event::CORE_THREAD_SUSPEND:
			ev = [self coreThreadSuspend: r];
			break;
		case Event::CORE_THREAD_WAKEUP:
			ev = [self coreThreadWakeup: r];
			break;
		case Event::CORE_THREAD_STEAL:
			ev = [self coreThreadSteal: r];
			break;
		case Event::CORE_THREAD_TERM:
			ev = [self coreThreadTerm: r];
			break;
		case Event::CORE_THREAD_SCHED:
			ev = [self coreThreadSched: r];
			break;
		case Event::CORE_THREAD_SIGNALWAKEUP:
			ev = [self coreThreadSignalWakeup: r];
			break;
		case Event::CORE_THREAD_LSTEAL:
			ev = [self coreThreadLsteal: r];
			break;
		case Event::CORE_THREAD_RETLSTEAL:
			ev = [self coreThreadRetLsteal: r];
			break;
		case Event::CORE_THREAD_RSTEAL:
			ev = [self coreThreadRsteal: r];
			break;
		case Event::CORE_THREAD_RETRSTEAL:
			ev = [self coreThreadRetRsteal: r];
			break;
		default:
			break;
	}
	if (ev != nil){
		[ev setTimestamp: timestamp];
		[ev setIdentifier: identifier];
	}
	return ev;
}

@end

